package tools

import (
	"errors"
	"sync"
)

var (
	ErrLogic = errors.New("component internal error")
)

type KeyLock struct {
	lock sync.RWMutex
	m    sync.Map
}

func NewKeyLock() *KeyLock {
	lm := &KeyLock{
		sync.RWMutex{},
		sync.Map{},
	}
	return lm
}

func (lm *KeyLock) store(key interface{}, e *Element) {
	lm.m.Store(key, e)
}

func (lm *KeyLock) isExist(key interface{}) bool {
	_, ok := lm.m.Load(key)
	return ok
}

func (lm *KeyLock) delete(key interface{}) {
	lm.m.Delete(key)
}

func (lm *KeyLock) load(key interface{}) (*Element, bool) {
	v, ok := lm.m.Load(key)
	if !ok {
		return nil, false
	}

	e, ok := v.(*Element)
	if !ok {
		// 内部数据类型不符  逻辑错误
		lm.delete(key)
		return nil, false
	}
	return e, true
}

func (lm *KeyLock) Enter(key interface{}) {
	<-func() <-chan struct{} {
		lm.lock.Lock()
		defer lm.lock.Unlock()

		e, ok := lm.load(key)
		if !ok {
			e = NewElement()
		}

		lm.store(key, e)

		return e.Wait()
	}()
}

func (lm *KeyLock) Leave(key interface{}) {
	lm.lock.Lock()
	defer lm.lock.Unlock()

	e, ok := lm.load(key)
	if !ok {
		// 当leave次数大于enter次数 就会跑到这里
		return
	}

	isLatest := e.Done()
	if isLatest {
		lm.delete(key)
	}

}

type Element struct {
	lock    sync.RWMutex
	count   int
	channel chan struct{}
}

func NewElement() *Element {
	e := &Element{
		sync.RWMutex{},
		0,
		make(chan struct{}),
	}
	return e
}

func (e *Element) Wait() <-chan struct{} {
	e.lock.Lock()
	defer e.lock.Unlock()
	e.count++
	if e.count == 1 {
		c := make(chan struct{}, 1)
		c <- struct{}{}
		return c
	} else {
		c := e.channel
		return c
	}
}

func (e *Element) Done() (isLatest bool) {
	e.lock.Lock()
	defer e.lock.Unlock()
	e.count--
	if e.count == 0 {
		close(e.channel)
		return true
	} else {
		e.channel <- struct{}{}
		return false
	}
}
